#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

void* subthread(void *arg)
{
    pthread_t mainthread = (pthread_t)arg;

    sleep(13);

    printf("signal to main thread.\n");
    pthread_kill(mainthread, SIGUSR1);

    return NULL;
}

void sigHandle(int signo)
{
    if (SIGUSR1 == signo)
    {
        return;
    }
    else
    {
        raise(signo);
    } 
}

int main(void)
{
    int fd = open("/dev/simple_epoll", O_RDONLY);

    if (-1 != fd)
    {
        struct epoll_event ev_globalfifo;
        int err;
        
        int epfd = epoll_create(1);
        if (epfd < 0)
        {
            perror("epoll_create(1)");
            return -1;
        }

        bzero(&ev_globalfifo, sizeof(struct epoll_event));
        ev_globalfifo.data.fd = fd;
        ev_globalfifo.events = EPOLLIN | EPOLLOUT | EPOLLET;
        err = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev_globalfifo);
        if (err < 0)
        {
            perror("epoll_ctl()");
            return -1;
        }
        
        signal(SIGUSR1, sigHandle);
        pthread_t tsub;
        pthread_create(&tsub, NULL, subthread, (void*)pthread_self());

        while (1)
        {
            err = epoll_wait(epfd, &ev_globalfifo, 1, -1);
            if (err < 0)
            {
                perror("epoll_wait()");
                break;
            }
            else if (err == 0)
            {
                printf("no event\n");
            }
            else
            {
                printf("err = %d, events = %d\n", err, ev_globalfifo.events);
                if (ev_globalfifo.events & EPOLLIN)
                {
                    printf("read event happen.\n");
                }
                if (ev_globalfifo.events & EPOLLOUT)
                {
                    printf("write event happen.\n");
                }
            }
        }
        
        printf("epoll_wait return.\n");
        err = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev_globalfifo);
        if (err < 0)
        {
            perror("epoll_ctl()");
        }

        close(fd);
        void* retval;
        pthread_join(tsub, &retval);
        
        printf("main thread return.\n");
    }
}